const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');

class DatabaseManager {
  constructor() {
    const dbDir = process.env.LANCHAT_DATA_DIR || path.join(__dirname, '../../data');
    if (!fs.existsSync(dbDir)) {
      fs.mkdirSync(dbDir, { recursive: true });
    }

    this.db = new Database(path.join(dbDir, 'lanchat.db'));
    this.initDatabase();
  }

  initDatabase() {
    // Messages table
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS messages (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        message_id TEXT UNIQUE NOT NULL,
        peer_id TEXT NOT NULL,
        sender_id TEXT NOT NULL,
        content TEXT,
        type TEXT NOT NULL,
        timestamp INTEGER NOT NULL,
        status TEXT DEFAULT 'sent'
      )
    `);

    // File transfers table
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS file_transfers (
        id TEXT PRIMARY KEY,
        file_name TEXT NOT NULL,
        file_size INTEGER NOT NULL,
        file_path TEXT,
        peer_id TEXT NOT NULL,
        sender_id TEXT NOT NULL,
        progress REAL DEFAULT 0,
        status TEXT DEFAULT 'pending',
        transfer_speed REAL,
        start_time INTEGER,
        end_time INTEGER
      )
    `);

    // Contacts table
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS contacts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        device_id TEXT UNIQUE NOT NULL,
        device_name TEXT,
        last_seen INTEGER,
        ip_address TEXT
      )
    `);

    // Create indexes
    this.db.exec(`
      CREATE INDEX IF NOT EXISTS idx_messages_peer_id ON messages(peer_id);
      CREATE INDEX IF NOT EXISTS idx_messages_timestamp ON messages(timestamp);
      CREATE INDEX IF NOT EXISTS idx_messages_message_id ON messages(message_id);
      CREATE INDEX IF NOT EXISTS idx_file_transfers_status ON file_transfers(status);
      CREATE INDEX IF NOT EXISTS idx_file_transfers_peer_id ON file_transfers(peer_id);
      CREATE INDEX IF NOT EXISTS idx_file_transfers_sender_id ON file_transfers(sender_id);
      CREATE INDEX IF NOT EXISTS idx_contacts_device_id ON contacts(device_id);
    `);
  }

  saveMessage(peerId, senderId, content, type, messageId) {
    const stmt = this.db.prepare(`
      INSERT INTO messages (message_id, peer_id, sender_id, content, type, timestamp)
      VALUES (?, ?, ?, ?, ?, ?)
    `);

    try {
      const result = stmt.run(messageId, peerId, senderId, content, type, Date.now());
      return result.lastInsertRowid;
    } catch (error) {
      // If message_id already exists, skip (avoid duplicates)
      if (error.code === 'SQLITE_CONSTRAINT') {
        console.log('Duplicate message ignored:', messageId);
        return null;
      }
      throw error;
    }
  }

  getMessageHistory(peerId, limit = 100, offset = 0) {
    // Get all messages where either sender or recipient is the specified peer
    const stmt = this.db.prepare(`
      SELECT * FROM messages
      WHERE peer_id = ? OR sender_id = ?
      ORDER BY timestamp DESC
      LIMIT ? OFFSET ?
    `);

    return stmt.all(peerId, peerId, limit, offset).reverse();
  }

  getMessageCount(peerId) {
    const stmt = this.db.prepare(`
      SELECT COUNT(*) as count FROM messages
      WHERE peer_id = ? OR sender_id = ?
    `);

    const result = stmt.get(peerId, peerId);
    return result.count;
  }

  saveFileTransfer(transferData) {
    const stmt = this.db.prepare(`
      INSERT INTO file_transfers
      (id, file_name, file_size, file_path, peer_id, sender_id, status, start_time)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `);

    stmt.run(
      transferData.id,
      transferData.fileName,
      transferData.fileSize,
      transferData.filePath,
      transferData.peerId,
      transferData.senderId,
      transferData.status,
      Date.now()
    );
  }

  updateFileTransferProgress(transferId, progress, speed) {
    const stmt = this.db.prepare(`
      UPDATE file_transfers
      SET progress = ?, transfer_speed = ?
      WHERE id = ?
    `);

    stmt.run(progress, speed, transferId);
  }

  completeFileTransfer(transferId) {
    const stmt = this.db.prepare(`
      UPDATE file_transfers
      SET status = 'completed', progress = 1.0, end_time = ?
      WHERE id = ?
    `);

    stmt.run(Date.now(), transferId);
  }

  saveContact(contact) {
    const stmt = this.db.prepare(`
      INSERT OR REPLACE INTO contacts (device_id, device_name, last_seen, ip_address)
      VALUES (?, ?, ?, ?)
    `);

    stmt.run(contact.id, contact.name, contact.lastSeen, contact.ipAddress);
  }

  getContacts() {
    const stmt = this.db.prepare('SELECT * FROM contacts ORDER BY last_seen DESC');
    return stmt.all();
  }

  close() {
    this.db.close();
  }
}

module.exports = DatabaseManager;
